/*

Copyright (c) 2021 唐佐林
WeChat : delphi_tang
EMail: delphi_tang@dt4sw.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "IPCClient.h"
#include "IPCEvent.h"
#include <QHostAddress>

IPCClient::IPCClient(QObject* parent) : QObject(parent), m_handler(NULL)
{
    connect(&m_client, SIGNAL(connected()), this, SLOT(onConnected()));
    connect(&m_client, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    connect(&m_client, SIGNAL(readyRead()), this, SLOT(onDataReady()));
    connect(&m_client, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
}

void IPCClient::onConnected()
{
    if( m_handler != NULL )
    {
        IPCMessage conn(IPC_TYPE_STATE, IPC_STATE_CONN, 0, 0);

        m_handler->handle(m_client, conn);
    }
}

void IPCClient::onDisconnected()
{
    m_assembler.reset();

    if( m_handler != NULL )
    {
        IPCMessage dscn(IPC_TYPE_STATE, IPC_STATE_DSCN, 0, 0, 0);

        m_handler->handle(m_client, dscn);
    }
}

void IPCClient::onDataReady()
{
    char buf[256] = {0};
    int len = 0;

    while( (len = m_client.read(buf, sizeof(buf))) > 0 )
    {  
        QSharedPointer<IPCMessage> ptm = NULL;

        m_assembler.prepare(buf, len);

        while( (ptm = m_assembler.assemble()) != NULL )
        {
            if( m_handler != NULL )
            {
                m_handler->handle(m_client, *ptm);
            }
        }
    }
}

void IPCClient::onBytesWritten(qint64 bytes)
{
    (void)bytes;
}

bool IPCClient::connectTo(QString ip, int port)
{
    bool ret = isValid();

    if( !ret )
    {
        m_client.setSocketOption(QAbstractSocket::KeepAliveOption, 1);
        m_client.connectToHost(ip, port);

        ret = m_client.waitForConnected(3000);
    }

    return ret;
}

qint64 IPCClient::send(const IPCMessage& message)
{
    qint64 ret = -1;

    if( isValid() )
    {
        QByteArray ba = message.serialize();

        ret = m_client.write(ba.data(), ba.length());

        m_client.flush();
    }

    return ret;
}

qint64 IPCClient::available()
{
    qint64 ret = -1;

    if( isValid() )
    {
        ret = m_client.bytesAvailable();
    }

    return ret;
}

void IPCClient::close()
{
    if( isValid() )
    {
        m_client.close();
    }
}

bool IPCClient::isValid()
{
    return (m_client.state() == QAbstractSocket::ConnectedState);
}

void IPCClient::setHandler(IPCMsgHandler* handler)
{
    m_handler = handler;
}
